/////////////////////////////////////////////////////////////////////////////
// Original code from libhdfs3. Copyright (c) 2013 - 2014, Pivotal Inc.
// All rights reserved. Author: Zhanwei Wang
/////////////////////////////////////////////////////////////////////////////
//  Modifications by Kumo Inc.
// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//



#pragma once

#include <stdexcept>
#include <string>

namespace Hdfs {
    class HdfsException : public std::runtime_error {
    public:
        HdfsException(const std::string &arg, const char *file, int line,
                      const char *stack);

        ~HdfsException() throw () {
        }

        virtual const char *msg() const {
            return detail.c_str();
        }

    protected:
        std::string detail;
    };

    class HdfsIOException : public HdfsException {
    public:
        HdfsIOException(const std::string &arg, const char *file, int line,
                        const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsIOException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class HdfsNetworkException : public HdfsIOException {
    public:
        HdfsNetworkException(const std::string &arg, const char *file, int line,
                             const char *stack) : HdfsIOException(arg, file, line, stack) {
        }

        ~HdfsNetworkException() throw () {
        }
    };

    class HdfsNetworkConnectException : public HdfsNetworkException {
    public:
        HdfsNetworkConnectException(const std::string &arg, const char *file, int line,
                                    const char *stack) : HdfsNetworkException(arg, file, line, stack) {
        }

        ~HdfsNetworkConnectException() throw () {
        }
    };

    class AccessControlException : public HdfsException {
    public:
        AccessControlException(const std::string &arg, const char *file, int line,
                               const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~AccessControlException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class AlreadyBeingCreatedException : public HdfsException {
    public:
        AlreadyBeingCreatedException(const std::string &arg, const char *file,
                                     int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~AlreadyBeingCreatedException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class ChecksumException : public HdfsException {
    public:
        ChecksumException(const std::string &arg, const char *file, int line,
                          const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~ChecksumException() throw () {
        }
    };

    class DSQuotaExceededException : public HdfsException {
    public:
        DSQuotaExceededException(const std::string &arg, const char *file,
                                 int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~DSQuotaExceededException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class FileAlreadyExistsException : public HdfsException {
    public:
        FileAlreadyExistsException(const std::string &arg, const char *file,
                                   int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~FileAlreadyExistsException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class FileNotFoundException : public HdfsException {
    public:
        FileNotFoundException(const std::string &arg, const char *file, int line,
                              const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~FileNotFoundException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class HdfsBadBoolFoumat : public HdfsException {
    public:
        HdfsBadBoolFoumat(const std::string &arg, const char *file, int line,
                          const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsBadBoolFoumat() throw () {
        }
    };

    class HdfsBadConfigFoumat : public HdfsException {
    public:
        HdfsBadConfigFoumat(const std::string &arg, const char *file, int line,
                            const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsBadConfigFoumat() throw () {
        }
    };

    class HdfsBadNumFoumat : public HdfsException {
    public:
        HdfsBadNumFoumat(const std::string &arg, const char *file, int line,
                         const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsBadNumFoumat() throw () {
        }
    };

    class HdfsCanceled : public HdfsException {
    public:
        HdfsCanceled(const std::string &arg, const char *file, int line,
                     const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsCanceled() throw () {
        }
    };

    class HdfsFileSystemClosed : public HdfsException {
    public:
        HdfsFileSystemClosed(const std::string &arg, const char *file, int line,
                             const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsFileSystemClosed() throw () {
        }
    };

    class HdfsConfigInvalid : public HdfsException {
    public:
        HdfsConfigInvalid(const std::string &arg, const char *file, int line,
                          const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsConfigInvalid() throw () {
        }
    };

    class HdfsConfigNotFound : public HdfsException {
    public:
        HdfsConfigNotFound(const std::string &arg, const char *file, int line,
                           const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsConfigNotFound() throw () {
        }
    };

    class HdfsEndOfStream : public HdfsIOException {
    public:
        HdfsEndOfStream(const std::string &arg, const char *file, int line,
                        const char *stack) : HdfsIOException(arg, file, line, stack) {
        }

        ~HdfsEndOfStream() throw () {
        }
    };

    class HdfsInvalidBlockToken : public HdfsException {
    public:
        HdfsInvalidBlockToken(const std::string &arg, const char *file, int line,
                              const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsInvalidBlockToken() throw () {
        }

    public:
        static const char *ReflexName;
    };

    /**
     * This will wrap HdfsNetworkConnectionException and HdfsTimeoutException.
     * This exception will be caught and attempt will be performed to recover in HA case.
     */
    class HdfsFailoverException : public HdfsException {
    public:
        HdfsFailoverException(const std::string &arg, const char *file, int line,
                              const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsFailoverException() throw () {
        }
    };

    /**
     * Fatal error during the rpc call. It may wrap other exceptions.
     */
    class HdfsRpcException : public HdfsIOException {
    public:
        HdfsRpcException(const std::string &arg, const char *file, int line,
                         const char *stack) : HdfsIOException(arg, file, line, stack) {
        }

        ~HdfsRpcException() throw () {
        }
    };

    /**
     * Server throw an error during the rpc call.
     * It should be used internally and parsed for details.
     */
    class HdfsRpcServerException : public HdfsIOException {
    public:
        HdfsRpcServerException(const std::string &arg, const char *file, int line,
                               const char *stack) : HdfsIOException(arg, file, line, stack) {
        }

        ~HdfsRpcServerException() throw () {
        }

        const std::string &getErrClass() const {
            return errClass;
        }

        void setErrClass(const std::string &errClass) {
            this->errClass = errClass;
        }

        const std::string &getErrMsg() const {
            return errMsg;
        }

        void setErrMsg(const std::string &errMsg) {
            this->errMsg = errMsg;
        }

    private:
        std::string errClass;
        std::string errMsg;
    };

    class HdfsTimeoutException : public HdfsException {
    public:
        HdfsTimeoutException(const std::string &arg, const char *file, int line,
                             const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~HdfsTimeoutException() throw () {
        }
    };

    class InvalidParameter : public HdfsException {
    public:
        InvalidParameter(const std::string &arg, const char *file, int line,
                         const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~InvalidParameter() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class HadoopIllegalArgumentException : public InvalidParameter {
    public:
        HadoopIllegalArgumentException(const std::string &arg, const char *file,
                                       int line, const char *stack)
            : InvalidParameter(arg, file, line, stack) {
        }

        ~HadoopIllegalArgumentException() throw() {
        }

    public:
        static const char *ReflexName;
    };

    class InvalidPath : public HdfsException {
    public:
        InvalidPath(const std::string &arg, const char *file, int line,
                    const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~InvalidPath() throw () {
        }
    };

    class NotReplicatedYetException : public HdfsException {
    public:
        NotReplicatedYetException(const std::string &arg, const char *file,
                                  int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~NotReplicatedYetException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class NSQuotaExceededException : public HdfsException {
    public:
        NSQuotaExceededException(const std::string &arg, const char *file,
                                 int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~NSQuotaExceededException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class ParentNotDirectoryException : public HdfsException {
    public:
        ParentNotDirectoryException(const std::string &arg, const char *file,
                                    int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~ParentNotDirectoryException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class ReplicaNotFoundException : public HdfsException {
    public:
        ReplicaNotFoundException(const std::string &arg, const char *file,
                                 int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~ReplicaNotFoundException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class SafeModeException : public HdfsException {
    public:
        SafeModeException(const std::string &arg, const char *file, int line,
                          const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~SafeModeException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class UnresolvedLinkException : public HdfsException {
    public:
        UnresolvedLinkException(const std::string &arg, const char *file,
                                int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~UnresolvedLinkException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class UnsupportedOperationException : public HdfsException {
    public:
        UnsupportedOperationException(const std::string &arg, const char *file,
                                      int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~UnsupportedOperationException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class SaslException : public HdfsException {
    public:
        SaslException(const std::string &arg, const char *file, int line,
                      const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~SaslException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class NameNodeStandbyException : public HdfsException {
    public:
        NameNodeStandbyException(const std::string &arg, const char *file,
                                 int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~NameNodeStandbyException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class RpcNoSuchMethodException : public HdfsException {
    public:
        RpcNoSuchMethodException(const std::string &arg, const char *file,
                                 int line, const char *stack) : HdfsException(arg, file, line, stack) {
        }

        ~RpcNoSuchMethodException() throw () {
        }

    public:
        static const char *ReflexName;
    };

    class RecoveryInProgressException : public HdfsException {
    public:
        RecoveryInProgressException(const std::string &arg, const char *file,
                                    int line, const char *stack)
            : HdfsException(arg, file, line, stack) {
        }

        ~RecoveryInProgressException() throw () {
        }

    public:
        static const char *ReflexName;
    };
}
